package service

import (
	"lsgfish/server/internal/dto/request"
	"lsgfish/server/internal/dto/response"
	"lsgfish/server/pkg/gcode"

	"gorm.io/gorm"
)

// GcodeService 数据库代码生成服务接口
type GcodeService interface {
	// 获取数据库结构树
	GetDatabaseStructure() ([]response.DatabaseInfo, error)
	// 获取表结构详情
	GetTableStructure(database, table string) (*response.TableStructure, error)
	// 生成代码 写入磁盘
	GenerateCode(request request.GenerateCodeRequest) (map[string]string, error)
	// 生成代码但不写入磁盘
	GenerateCodeInMemory(request request.GenerateCodeRequest) (map[string]string, error)
}

// gcodeServiceImpl 数据库代码生成服务实现
type gcodeServiceImpl struct {
	db   *gorm.DB
	repo gcode.GcodeRepo
}

// 创建新的GcodeService实例
func NewGcodeService(db *gorm.DB) GcodeService {
	return &gcodeServiceImpl{
		db:   db,
		repo: gcode.NewGcodeRepo(db),
	}
}

// GetDatabaseStructure 获取数据库结构树
func (s *gcodeServiceImpl) GetDatabaseStructure() ([]response.DatabaseInfo, error) {
	// 获取当前数据库名
	currentDB, err := s.repo.GetCurrentDatabaseName()
	if err != nil {
		return nil, err
	}

	// 获取所有数据库
	databases, err := s.repo.GetAllDatabases()
	if err != nil {
		return nil, err
	}

	// 构建返回结果
	var result []response.DatabaseInfo

	for _, dbName := range databases {
		// 排除系统数据库
		if dbName == "information_schema" || dbName == "mysql" || dbName == "performance_schema" || dbName == "sys" {
			continue
		}

		// 获取该数据库下的所有表
		tables, err := s.repo.GetDatabaseTables(dbName)
		if err != nil {
			return nil, err
		}

		// 构建表信息列表
		var tableInfos []response.TableInfo
		for _, tableName := range tables {
			tableInfos = append(tableInfos, response.TableInfo{
				Name: tableName,
				Type: "table",
			})
		}

		// 添加到结果
		dbInfo := response.DatabaseInfo{
			Name:    dbName,
			Tables:  tableInfos,
			Current: dbName == currentDB,
		}
		result = append(result, dbInfo)
	}

	return result, nil
}

// GetTableStructure 获取表结构详情
func (s *gcodeServiceImpl) GetTableStructure(database, table string) (*response.TableStructure, error) {
	pkgTableStructure, err := s.repo.GetTableStructure(database, table)
	if err != nil {
		return nil, err
	}

	// 转换为内部DTO结构
	var columns []response.ColumnInfo
	for _, col := range pkgTableStructure.Columns {
		columns = append(columns, response.ColumnInfo{
			Name:         col.Name,
			Type:         col.Type,
			Key:          col.Key,
			Nullable:     col.Nullable,
			DefaultValue: col.DefaultValue,
			Extra:        col.Extra,
			Comment:      col.Comment,
		})
	}

	var indexes []response.IndexInfo
	for _, idx := range pkgTableStructure.Indexes {
		indexes = append(indexes, response.IndexInfo{
			Name:      idx.Name,
			NonUnique: idx.NonUnique,
			Columns:   idx.Columns,
		})
	}

	return &response.TableStructure{
		Name:        pkgTableStructure.Name,
		Engine:      pkgTableStructure.Engine,
		Comment:     pkgTableStructure.Comment,
		CreateTime:  pkgTableStructure.CreateTime,
		UpdateTime:  pkgTableStructure.UpdateTime,
		Columns:     columns,
		PrimaryKeys: pkgTableStructure.PrimaryKeys,
		Indexes:     indexes,
	}, nil
}

// GenerateCode 生成代码
func (s *gcodeServiceImpl) GenerateCode(request request.GenerateCodeRequest) (map[string]string, error) {
	// 使用代码生成器生成代码
	generator := gcode.NewGenerator(s.db, request)
	return generator.Generate()
}

// GenerateCodeInMemory 生成代码但不写入磁盘
func (s *gcodeServiceImpl) GenerateCodeInMemory(request request.GenerateCodeRequest) (map[string]string, error) {
	// 使用代码生成器生成代码，但不写入磁盘
	generator := gcode.NewGenerator(s.db, request)
	return generator.GenerateInMemory()
}
